package fatworm.concept;

import fatworm.util.Lib;

/**
 * data type supported by Fat worm 
 * data type shall be supported by singleton 
 */
public abstract class DataType {
	/* must implement toString */
	public abstract String toString();
	/** return the type key to quickly find which type it is */
	public abstract int getTypeKey(); 
	
	/**
	 * convert the value to current data type,
	 * if the value is already current type ,
	 * return the value directly 
	 * @param value the value to be converted
	 * @return the converted value
	 * @throws ConvertException
	 */
	public abstract SqlValue convert( SqlValue value ) throws ConvertException;
	
	/**
	 * 	values that may stored in a table
	 */
	public abstract class SqlValue {
		/* value must implement to String */
		public abstract String toString();	
		/** @return whether the value is null */
		public boolean isNull(){
			return false;
		}
		/** @return the type of the value */
		public DataType getType(){
			return DataType.this;
		}
	}

	
	/** keys used to quickly find the data type */
	public static final int T_NULL = 0 ,T_INT = 1, T_FLOAT = 2 , 
							T_STRING = 3 , T_BOOLEAN = 4 , T_CHAR = 5 , 
							T_VARCHAR = 6 , T_DATETIME = 7 , T_TIMESTAMP = 8,
							T_DECIMAL = 9; 
	
	public static final FatNull.NullValue nullValue =  FatNull.getInstance().getNull();
	/**
	 * @return null value 
	 */
	public static final FatNull.NullValue getNullValue(){
		return nullValue;
	}
	/** exception throws out during convert */
	public static class ConvertException extends java.lang.RuntimeException{
		private static final long serialVersionUID = 1L;
		public SqlValue from;
		public DataType  to;
		public ConvertException( SqlValue from , DataType to ){
			this.from = from; this.to = to;
		}
		public String toString(){
			return "ConvertException from " + from + " to " + to;
		}
	}
}
/**
 * null type
 */
class FatNull extends DataType{
	private static FatNull instance = new FatNull();
	public static FatNull getInstance(){
		return instance;
	}
	private FatNull(){}
	private NullValue nullValue = new NullValue(); 
	/**
	 * @return null
	 */
	public NullValue getNull(){
		return nullValue;
	}
	public SqlValue convert(SqlValue value) throws ConvertException {
		Lib.assertNotReached();
		return null;
	}
	public int getTypeKey() {
		return T_NULL;
	}
	public String toString() {
		return "null";
	}
	public class NullValue extends SqlValue{
		private NullValue(){}
		public String toString(){
			return "NULL";
		}
	}
	
}
